﻿using System;
using System.Collections.Generic;
using System.Linq;
using Lucene.Net.Search;
using Medianamik.Core.Interfaces;

namespace Medianamik.Core.Index
{
	public class SearchResult
	{

		#region .ctor
		internal SearchResult(Hits pHits)
		{
			if (pHits == null)
			{
				throw new ArgumentNullException("pHits");
			}
            
            for (int i = 0; i < pHits.Length(); i++)
			{
				var nodeId = new Guid(pHits.Doc(i).Get("NodeId"));
                if (!NodeIdsInternal.ContainsKey(nodeId))
                {
                    NodeIdsInternal.Add(nodeId, pHits.Score(i));
                }
			}
            
		}

        private SearchResult()
        {
            
        }
		#endregion

		//TODO:Déplacer dans les configurations
		private const int DEFAULT_PAGE_SIZE = 20;

	    private static SearchResult _empty;
	    public static SearchResult Empty
	    {
	        get
	        {
	            return _empty ?? (_empty = new SearchResult());
	        }
	    }

		public int PageCount 
		{
			get
			{
				return 1 + (HitCount / PageSize);
			}
	}
		private int? _pageSize;
		public int PageSize
		{
			get
			{
				return _pageSize ?? DEFAULT_PAGE_SIZE;
			}
			set
			{
				if (value < 1)
				{
					throw new ArgumentOutOfRangeException("PageSize");
				}
				_pageSize = value;
			}
		}
        public int HitCount { get { return NodeIdsInternal.Count ; } }

		

		private Dictionary<Guid, float> _nodeIds;
        private Dictionary<Guid,float> NodeIdsInternal
	    {
	        get
	        {
                return _nodeIds ?? (_nodeIds = new Dictionary<Guid,float>());
	        }
	    }
		
		public Guid[] NodeIds
		{
			get
			{
                return NodeIdsInternal.Select(p=>p.Key).ToArray();
			}
		}

		public Node[] GetNodes()
		{
            return NodeManager.GetNodes(NodeIds)
                 .OrderByDescending(n => NodeIdsInternal[n.ID])
                .ToArray();
		}
		public Node[] GetNodes(int pPage)
		{
            var range = NodeIdsInternal.Skip(pPage * PageSize).Take(PageSize).Select(p => p.Key);
            return NodeManager.GetNodes(range.ToArray())
                .OrderByDescending(n => NodeIdsInternal[n.ID])
                .ToArray();
		}
		public T[] GetNodes<T>() where T:INodeWrapper,new()
		{
            return GetNodes()
                .Select(n => new T { InnerNode = n })
                .ToArray();
		}
        public T[] GetNodes<T>(int pPage) where T : INodeWrapper, new()
		{
            return GetNodes(pPage)
                .Select(n => new T { InnerNode = n })
                .ToArray();
		}
	}
}
